package edu.rpi.tw.escience.stargazer.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Application implements EntryPoint {

    /**
     * This is the entry point method.
     */

    private StargazerRemoteServiceAsync stargazerService = null;

    //private RootPanel mainPanel = RootPanel.get("StarGazer-Panel");

    private VerticalPanel inputPanel = new VerticalPanel();

    private VerticalPanel outputPanel = new VerticalPanel();

    private VerticalPanel timePanel = new VerticalPanel();
    private VerticalPanel datePanel = new VerticalPanel();
    private HorizontalPanel dateTimePanel = new HorizontalPanel();
    private VerticalPanel dateTimePanelwLabel = new VerticalPanel();

    private VerticalPanel userLatPanel = new VerticalPanel();
    private VerticalPanel userLongPanel = new VerticalPanel();
    private HorizontalPanel userCoordPanel = new HorizontalPanel();
    private VerticalPanel userCoordPanelwLabel = new VerticalPanel();

    private VerticalPanel skyLatPanel = new VerticalPanel();
    private VerticalPanel skyLongPanel = new VerticalPanel();
    private HorizontalPanel skyCoordPanel = new HorizontalPanel();
    private VerticalPanel skyCoordPanelwLabel = new VerticalPanel();

    FlexTable OutputTable = new FlexTable();

    final TextFieldWidget UserLat = new TextFieldWidget("Latitude", "45");
    final TextFieldWidget UserLong = new TextFieldWidget("Longitude", "-90");

    final TextFieldWidget SkyRA1 = new TextFieldWidget("Right Ascension 1", "-20h4m30s");
    final TextFieldWidget SkyRA2 = new TextFieldWidget("Right Ascension 2", "20h4m30s");
    final TextFieldWidget SkyDecl1 = new TextFieldWidget("Declination 1", "-30°52'0\"");
    final TextFieldWidget SkyDecl2 = new TextFieldWidget("Declination 2", "70°52'0\"");

    Date X = new Date();
    final TextFieldWidget TimePanelDate = new TextFieldWidget("Day", Integer.toString(X.getDate()));
    final TextFieldWidget TimePanelMonth = new TextFieldWidget("Month", Integer.toString(X.getMonth() + 1));
    final TextFieldWidget TimePanelYear = new TextFieldWidget("Year", Integer.toString(X.getYear() + 1900));

    final TextFieldWidget TimePanelHour = new TextFieldWidget("Hour", Integer.toString(X.getHours()));
    final TextFieldWidget TimePanelMinute = new TextFieldWidget("Minute", Integer.toString(X.getMinutes()));
    final TextFieldWidget TimePanelSecond = new TextFieldWidget("Second", Integer.toString(X.getSeconds()));

    final TextFieldWidget StarName = new TextFieldWidget("Name", "");

    final TextFieldWidget StarNGC = new TextFieldWidget("NGC", "");


    private Button locButton;
    private Button nameButton;
    private Button ngcButton;

    private Button backButton;

    public void callStargazerLocService(String[] UserCoordinates, String[] SkyCoordinates, String[] TimeInformation) {

        System.out.println("Entered Application:callStargazerLocService");
        getStargazerServiceInstance().getStars(UserCoordinates, SkyCoordinates, TimeInformation, new AsyncCallback() {
            public void onFailure(Throwable caught) {

                Window.alert("Failed to get response from server");
            }

            public void onSuccess(Object result) {
                //			System.out.println("Returned from server: " + result);
                Collection<Map<String, String>> foundStars = (Collection<Map<String, String>>) result;

                int i = 1;
                OutputTable.setHTML(i, 0, "");
                OutputTable.setHTML(i, 1, "");
                OutputTable.setHTML(i, 2, "");
                OutputTable.setHTML(i, 3, "");
                OutputTable.setHTML(i, 4, "");
                OutputTable.setHTML(i, 5, "");
                OutputTable.setHTML(i, 6, "");
                OutputTable.setHTML(i, 7, "");
                OutputTable.setHTML(i, 8, "");
                OutputTable.setHTML(i, 9, "");
                OutputTable.setHTML(i, 10, "");
                OutputTable.setHTML(i, 11, "");

                for (Map<String, String> star : foundStars) {
                    if (star.containsKey("NAME")) {
                        OutputTable.setHTML(i, 0, createLinkHTML(star.get("URI"), star.get("NAME")));
                    }
                    if (star.containsKey("MESSIER_NUMBER"))
                        OutputTable.setHTML(i, 1, star.get("MESSIER_NUMBER"));
                    if (star.containsKey("NGC_NUMBER"))
                        OutputTable.setHTML(i, 2, star.get("NGC_NUMBER"));
                    if (star.containsKey("RIGHT_ASCENSION"))
                        OutputTable.setHTML(i, 3, star.get("RIGHT_ASCENSION"));
                    if (star.containsKey("DECLINATION"))
                        OutputTable.setHTML(i, 4, star.get("DECLINATION"));
                    if (star.containsKey("ABSOLUTE_MAGNITUDE"))
                        OutputTable.setHTML(i, 5, star.get("ABSOLUTE_MAGNITUDE"));
                    if (star.containsKey("APPARENT_MAGNITUDE"))
                        OutputTable.setHTML(i, 6, star.get("APPARENT_MAGNITUDE"));
                    if (star.containsKey("LUMINOSITY"))
                        OutputTable.setHTML(i, 7, star.get("LUMINOSITY"));
                    if (star.containsKey("SOLAR_MASSES"))
                        OutputTable.setHTML(i, 8, star.get("SOLAR_MASSES"));
                    if (star.containsKey("MEAN_SOLAR_RADIUS"))
                        OutputTable.setHTML(i, 9, star.get("MEAN_SOLAR_RADIUS"));
                    if (star.containsKey("METALLICITY"))
                        OutputTable.setHTML(i, 10, star.get("METALLICITY"));
                    if (star.containsKey("SPECTRAL_TYPE"))
                        OutputTable.setHTML(i, 11, star.get("SPECTRAL_TYPE"));
                    i++;
                }

                inputPanel.setVisible(false);
                outputPanel.setVisible(true);
            }
        });
    }

    public void callStargazerNameService(String name) {
        getStargazerServiceInstance().getStarByName(name, new AsyncCallback() {
            public void onFailure(Throwable caught) {

                Window.alert("Failed to get response from server");
            }

            public void onSuccess(Object result) {
                //			System.out.println("Returned from server: " + result);
                Map<String, String> star = (Map<String, String>) result;

                int i = 1;
                OutputTable.setHTML(i, 0, "");
                OutputTable.setHTML(i, 1, "");
                OutputTable.setHTML(i, 2, "");
                OutputTable.setHTML(i, 3, "");
                OutputTable.setHTML(i, 4, "");
                OutputTable.setHTML(i, 5, "");
                OutputTable.setHTML(i, 6, "");
                OutputTable.setHTML(i, 7, "");
                OutputTable.setHTML(i, 8, "");
                OutputTable.setHTML(i, 9, "");
                OutputTable.setHTML(i, 10, "");
                OutputTable.setHTML(i, 11, "");

                if (star.containsKey("NAME")) {
                    OutputTable.setHTML(i, 0, createLinkHTML(star.get("URI"), star.get("NAME")));
                }
                if (star.containsKey("MESSIER_NUMBER"))
                    OutputTable.setHTML(i, 1, star.get("MESSIER_NUMBER"));
                if (star.containsKey("NGC_NUMBER"))
                    OutputTable.setHTML(i, 2, star.get("NGC_NUMBER"));
                if (star.containsKey("RIGHT_ASCENSION"))
                    OutputTable.setHTML(i, 3, star.get("RIGHT_ASCENSION"));
                if (star.containsKey("DECLINATION"))
                    OutputTable.setHTML(i, 4, star.get("DECLINATION"));
                if (star.containsKey("ABSOLUTE_MAGNITUDE"))
                    OutputTable.setHTML(i, 5, star.get("ABSOLUTE_MAGNITUDE"));
                if (star.containsKey("APPARENT_MAGNITUDE"))
                    OutputTable.setHTML(i, 6, star.get("APPARENT_MAGNITUDE"));
                if (star.containsKey("LUMINOSITY"))
                    OutputTable.setHTML(i, 7, star.get("LUMINOSITY"));
                if (star.containsKey("SOLAR_MASSES"))
                    OutputTable.setHTML(i, 8, star.get("SOLAR_MASSES"));
                if (star.containsKey("MEAN_SOLAR_RADIUS"))
                    OutputTable.setHTML(i, 9, star.get("MEAN_SOLAR_RADIUS"));
                if (star.containsKey("METALLICITY"))
                    OutputTable.setHTML(i, 10, star.get("METALLICITY"));
                if (star.containsKey("SPECTRAL_TYPE"))
                    OutputTable.setHTML(i, 11, star.get("SPECTRAL_TYPE"));

                inputPanel.setVisible(false);
                outputPanel.setVisible(true);
            }
        });

    }


    private StargazerRemoteServiceAsync getStargazerServiceInstance() {
        if (stargazerService == null) {
            // Instantiate the service
            stargazerService = (StargazerRemoteServiceAsync) GWT.create(StargazerRemoteService.class);
            String moduleRelativeURL = GWT.getModuleBaseURL()
                    + "stargazerRemoteService";

            ((ServiceDefTarget) stargazerService).setServiceEntryPoint(moduleRelativeURL);
        }
        return stargazerService;
    }


    private void renderInputScreen() {

        inputPanel.add(new HTML("<b>Enter your information:</b>"));
        inputPanel.add(new HTML("<br>"));

        userCoordPanelwLabel.setStyleName("stringReverserverWidget");
        userCoordPanel.add(UserLat);
        userCoordPanel.add(UserLong);
        //userCoordPanel.add(userLatPanel);
        //userCoordPanel.add(userLongPanel);

        userCoordPanelwLabel.add(new Label("Enter User Coordinates:"));
        userCoordPanelwLabel.add(userCoordPanel);

        inputPanel.add(userCoordPanelwLabel);
        inputPanel.add(new HTML("<br>"));

        skyCoordPanelwLabel.setStyleName("stringReverserverWidget");
        skyLatPanel.add(SkyRA1);
        skyLatPanel.add(SkyRA2);
        skyLongPanel.add(SkyDecl1);
        skyLongPanel.add(SkyDecl2);

        skyCoordPanel.add(skyLatPanel);
        skyCoordPanel.add(skyLongPanel);

        skyCoordPanelwLabel.add(new Label("Enter Sky Coordinates:"));
        skyCoordPanelwLabel.add(skyCoordPanel);

        inputPanel.add(skyCoordPanelwLabel);
        inputPanel.add(new HTML("<br>"));

        dateTimePanelwLabel.setStyleName("stringReverserverWidget");
        datePanel.add(TimePanelDate);
        datePanel.add(TimePanelMonth);
        datePanel.add(TimePanelYear);

        timePanel.add(TimePanelHour);
        timePanel.add(TimePanelMinute);
        timePanel.add(TimePanelSecond);

        dateTimePanel.add(datePanel);
        dateTimePanel.add(timePanel);

        dateTimePanelwLabel.add(new Label("Enter desired time:"));
        dateTimePanelwLabel.add(dateTimePanel);

        inputPanel.add(dateTimePanelwLabel);
        inputPanel.add(new HTML("<br>"));

        // Setup the button to call the service
        locButton = new Button();

        locButton.setText("Search By Location");


        locButton.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                String[] UserCoordinates = {UserLat.getTextValue(),
                        UserLong.getTextValue()
                };

                String[] SkyCoordinates = {SkyRA1.getTextValue(),
                        SkyRA2.getTextValue(),
                        SkyDecl1.getTextValue(),
                        SkyDecl2.getTextValue()
                };

                String[] TimeInformation = {
                        TimePanelYear.getTextValue(),
                        TimePanelMonth.getTextValue(),
                        TimePanelDate.getTextValue(),
                        TimePanelHour.getTextValue(),
                        TimePanelMinute.getTextValue(),
                        TimePanelSecond.getTextValue()
                };

                callStargazerLocService(UserCoordinates, SkyCoordinates, TimeInformation);
            }
        });

        // Add the button to the base panel
        inputPanel.add(locButton);

        inputPanel.add(new HTML("<br>"));
        // Setup the button to call the service
        nameButton = new Button();

        nameButton.setText("Search By Name");

        nameButton.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                callStargazerNameService(StarName.getTextValue());
            }
        });

        // Add the button to the base panel
        inputPanel.add(StarName);
        inputPanel.add(nameButton);

        inputPanel.add(new HTML("<br>"));
        // Setup the button to call the service
        ngcButton = new Button();

        ngcButton.setText("Search By NGC Number");

        ngcButton.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                //callStargazerNGCService(TimePanelStarName.getTextValue());
            }
        });

        inputPanel.add(StarNGC);
        inputPanel.add(ngcButton);

        inputPanel.add(new HTML("<br>"));

    }


    public void renderOutputScreen() {
        backButton = new Button();

        outputPanel.add(new HTML("<b>Returned Stars: </b>"));

        OutputTable.setHTML(0, 0, "Name");
        OutputTable.setHTML(0, 1, "Messier Number");
        OutputTable.setHTML(0, 2, "NGC Number");
        OutputTable.setHTML(0, 3, "Right Ascension");
        OutputTable.setHTML(0, 4, "Declination");
        OutputTable.setHTML(0, 5, "Absolute Magnitude");
        OutputTable.setHTML(0, 6, "Apparent Magnitude");
        OutputTable.setHTML(0, 7, "Luminosity");
        OutputTable.setHTML(0, 8, "Solar Masses");
        OutputTable.setHTML(0, 9, "Mean Solar Radius");
        OutputTable.setHTML(0, 10, "Metallicity");
        OutputTable.setHTML(0, 11, "Spectral Type");

        OutputTable.setHTML(1, 3, "<br> ");
        OutputTable.setBorderWidth(1);
        backButton.setText("Back");

        backButton.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                inputPanel.setVisible(true);
                outputPanel.setVisible(false);
            }
        });
        outputPanel.add(backButton);
        outputPanel.add(OutputTable);

    }

    public void onModuleLoad() {
        renderInputScreen();
        renderOutputScreen();
        inputPanel.setVisible(true);
        outputPanel.setVisible(false);

        RootPanel.get().add(inputPanel);
        RootPanel.get().add(outputPanel);
    }

    public static String createLinkHTML(final String uri,
                                        final String name) {
        String localName = uri.substring(uri.lastIndexOf("#") + 1);

        String s = "<a href=\"/stargazer-alpha1/rest/" + localName + "\">" + name + "</a>";
        return s;
    }
}
